// time_advance.cpp
// this program can be written easier with boost ptime_facet.
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <locale>
#include <cstdlib>
#include <cctype>

#include <boost/date_time/posix_time/posix_time.hpp>

#include "from_yyyyddd_string.h"

using namespace std;
using namespace boost::posix_time;
using namespace boost::gregorian;

int main(int argc, char *argv[])
{
	ptime start_t;
	ptime end_t;
	time_duration duration;
	
	time_facet *facet = 0;
	time_input_facet *input_facet = 0;

	string facet_str;

	if(argc < 3)
	{
		cout << "Usage: " << endl;
		cout << "    time_advance 2009153 110000 24" << endl;
		cout << "    time_advance 20090325 230000 10d" << endl;
		cout << "    time_advance 20090630120000 60m" << endl;
		cout << "    time_advance 20091231T235959 3600s" << endl;
		return 1;
	}
	else
	{
		// treat the last arg as duration.
		string duration_str = argv[argc - 1];

		stringstream ss;
		long duration_num;
		ss << duration_str;
		ss >> duration_num;
		switch(duration_str[duration_str.length() - 1])
		{
		case 'd':
			duration = hours(duration_num * 24);
			break;
		case 'm':
			duration = minutes(duration_num);
			break;
		case 's':
			duration = seconds(duration_num);
			break;
		default:
			duration = hours(duration_num);
		}
	}

	// treat the rest args as date time, and paste them together
	stringstream ss;
	string total_date_time;
	for(int i = 1; i <= argc - 2; ++i)
	{
		total_date_time = total_date_time + argv[i];
		if(i != argc - 2)
			total_date_time += " ";
	}
	ss << total_date_time;

	// distinguish the different formats
	if(argc >= 3)  //date and time are written together
	{
		int len = total_date_time.length();
		
		char delim = '_'; //e.g '_' in yyyymmdd_HHMMSS
		char delim1 = ':'; //e.g ':' in HH:MM:SS
		char delim2 = ':'; 

		switch(len)
		{
		case 7:		//yyyyddd
			facet_str = "%Y%j";
			break;
		case 8:		//yyyymmdd
			facet_str = "%Y%m%d";
			break;
		case 9:		//yyyydddHH
			facet_str = "%Y%j%H";
			break;
		case 10:	//yyyymmddHH or yyyyddd_HH
			if(isdigit(total_date_time[7]))
			{
				facet_str = "%Y%m%d%H";
			}
			else
			{
				delim = total_date_time[8];
				facet_str = string("%Y%j") + delim + "%H";
			}
			break;
		case 11:	//yyyymmdd?HH or yyyydddHHMM
			if(!isdigit(total_date_time[8]))
			{
				delim = total_date_time[8];
				facet_str = string("%Y%m%d") + delim + "%H";
			}
			else
			{
				facet_str = "%Y%j%H%M";
			}
			break;
		case 12:	//yyyymmddHHMM or yyyyddd_HHMM
			if(isdigit(total_date_time[7]))
			{
				facet_str = "%Y%m%d%H%M";
			}
			else
			{
				delim = total_date_time[7];
				facet_str = string("%Y%j") + delim + "%H%M";
			}
			break;
		case 13:	//yyyymmdd?HHMM or yyyydddHHMMSS
			if(!isdigit(total_date_time[8]))
			{
				delim = total_date_time[8];
				facet_str = string("%Y%m%d") + delim + "%H%M";
			}
			else
			{
				facet_str = "%Y%j%H%M%S";
			}
			break;
		case 14:	//yyyymmddHHMMSS or yyyymmdd_HH:MM or yyyyddd_HHMMSS
			if(isdigit(total_date_time[7]) && isdigit(total_date_time[8]))
			{
				facet_str = "%Y%m%d%H%M%S";
			}
			else if(isdigit(total_date_time[7]))
			{
				delim = total_date_time[8];
				delim1 = total_date_time[11];
				facet_str = string("%Y%m%d") + delim + "%H" + delim1 + "%S";
			}
			else
			{
				delim = total_date_time[7];
				facet_str = string("%Y%j") + delim + "%H%M%S";
			}
			break;
		case 15:	//yyyymmdd?HHMMSS
			delim = total_date_time[8];
			facet_str = string("%Y%m%d") + delim + "%H%M";
			break;
		case 16:	//yyyyddd_HH:MM:SS
			delim = total_date_time[7];
			delim1 = total_date_time[10];
			delim2 = total_date_time[13];
			facet_str = string("%Y%j") + delim + "%H" + delim1 + "%M" + delim2 + "%S";
			break;
		case 17:	//yyyymmdd_HH:MM:SS
			delim = total_date_time[8];
			delim1 = total_date_time[11];
			delim2 = total_date_time[14];
			facet_str = string("%Y%m%d") + delim + "%H" + delim1 + "%M" + delim2 + "%S";
			break;
		default:
			return 1;
		}
	}

	else
	{
		return 1;
	}

	facet = new time_facet(facet_str.c_str());
	input_facet = new time_input_facet(facet_str.c_str());

	ss.imbue(locale(ss.getloc(), input_facet));

	try
	{
		ss >> start_t;	
	}
	catch(...)
	{
		delete facet;
		delete input_facet;
		return 1;
	}
	
	end_t = start_t + duration;
	
	cout.imbue(locale(cout.getloc(), facet));
	cout << end_t << endl;
	
	delete facet;
	delete input_facet;
	return 0;
}
